package yartiss.engine.simulation;

import yartiss.engine.simulation.system.ITask;
import yartiss.engine.simulation.system.schedulable.Job;

public class Processor {
	private final int id;
	private final double cpuFrequency; 
	private final double cpuVoltage;
	private ITask currentTask = null;
	private ITask nextTask = null;

	public Processor(int id, double cpuFrequency, double cpuVoltage){
		this.id = id;
		this.cpuFrequency = cpuFrequency;
		this.cpuVoltage = cpuVoltage;
	}

	/**
	 * @return the currentTask
	 */
	public ITask getCurrentTask() {
		return currentTask;
	}

	/**
	 * @param currentTask the currentTask to set
	 */
	public void setCurrentTask(ITask currentTask) {
		this.currentTask = currentTask;
	}

	/**
	 * @return the id
	 */
	public int getId() {
		return id;
	}

	/**
	 * @return the cpuFrequency
	 */
	public double getCpuFrequency() {
		return cpuFrequency;
	}

	/**
	 * @return the cpuVoltage
	 */
	public double getCpuVoltage() {
		return cpuVoltage;
	}

	/**
	 * @return the oldTask
	 */
	public ITask getNextTask() {
		return nextTask;
	}

	/**
	 * @param nextTask the nextTask to set
	 */
	public void setNextTask(ITask nextTask) {
		this.nextTask = nextTask;
	}

	/**
	 * simulate the fact this task has been executed during elapsedTime tu. This
	 * has effects on the current task job and on the simulator energy level.
	 * 
	 * @param elapsedTime
	 * @return the energy consumed
	 */
	public long execute(long elapsedTime, IEnergyProfile energyProfile) {
		if(currentTask == null) return 0;

		assert currentTask.isActive();
		return execute(currentTask, currentTask.getCurrentJob(), elapsedTime,  energyProfile);
	}

	private long execute(ITask task, Job job,  long duration, IEnergyProfile energyProfile) {

		assert duration >= 0;

		if (duration == 0) {
			task.setLastExecutedJob(job);
			return 0;
		}

		long romainingCost = job.getRomainingTimeCost();

		// Energy
		long consumed = energyProfile.isGolobalConsumptionProfile() ?  energyProfile.getGlobalEnergyConsumptionProfile().getConsumed(task.getWcet(), task.getWcee(), romainingCost, duration) : task.getEnergyConsumption(duration);

		// Time
		job.consumeProcTime(duration);
		if (job.getRomainingTimeCost() == 0) {
			task.getActiveJobs().poll();
		}
		task.setLastExecutedJob(job);

		assert consumed * task.getWcet() == duration * task.getWcee() : "wcee not divisible by wcet";
		job.consumeEnergy(consumed);

		assert job.getRomainingEnergyCost() >= 0 : "date : "+task.getId() + " has consumed more energy than wcee";
		assert job.getRomainingTimeCost() >= 0 : task.getId() + " has consumed more time than wcet";

		return consumed;
	}






}
